home *** CD-ROM | disk | FTP | other *** search
- Subject: REPOST v22i052: NN Newsreader, release 6.4, Part16/21
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: f91ab175 078d3c43 4ad0d623 0d7e5c9d
-
- Submitted-by: "Kim F. Storm" <storm@texas.dk>
- Posting-number: Volume 22, Issue 51
- Archive-name: nn6.4/part16
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: collect.c doc/NEWS-6.4 doc/NNTP inews/clientlib.c prefix.c
- # Wrapped by rsalz@litchi.bbn.com on Fri May 11 12:43:14 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive."'
- if test -f 'collect.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'collect.c'\"
- else
- echo shar: Extracting \"'collect.c'\" \(11227 characters\)
- sed "s/^X//" >'collect.c' <<'END_OF_FILE'
- X/*
- X * (c) Copyright 1990, Kim Fabricius Storm. All rights reserved.
- X *
- X * Collect and save article information in database.
- X */
- X
- X#include "config.h"
- X#include "db.h"
- X#include "news.h"
- X
- X#define COUNT_RE_REFERENCES /* no of >>> depends on Reference: line */
- X
- Xexport int ignore_bad_articles = 1; /* no Newsgroups: line */
- Xexport int remove_bad_articles = 0;
- Xexport time_t max_article_age = 0;
- X
- Ximport int trace, debug_mode;
- X
- Xextern time_stamp pack_date();
- X
- Xstatic long bad_count;
- X
- Xstatic FILE *ix, *data;
- X
- Xstatic do_auto_archive(gh, f, num)
- Xgroup_header *gh;
- Xregister FILE *f;
- Xarticle_number num;
- X{
- X char line[200];
- X article_number last;
- X register FILE *arc;
- X register int c;
- X off_t start;
- X static char *arc_header = "Archived-Last: ";
- X /* Header format: Archived-Last: 88888888 group.name */
- X /* Fixed constants length == 15 and offset == 24 are used below */
- X
- X arc = open_file(gh->archive_file, OPEN_READ);
- X last = 0;
- X start = 0;
- X if (arc != NULL) {
- X while (fgets(line, 200, arc) != NULL) {
- X if (strncmp(line, arc_header, 15)) {
- X log_entry('E', "%s not archive for %s\n",
- X gh->archive_file, gh->group_name);
- X gh->master_flag &= ~M_AUTO_ARCHIVE;
- X fclose(arc);
- X return;
- X }
- X if (strncmp(line + 24, gh->group_name, gh->group_name_length)) {
- X start = ftell(arc);
- X continue;
- X }
- X last = atol(line + 15);
- X break;
- X }
- X fclose(arc);
- X arc = NULL;
- X }
- X
- X if (last >= num) return;
- X
- X arc = open_file(gh->archive_file, last > 0 ? OPEN_UPDATE : OPEN_CREATE);
- X if (arc == NULL) {
- X log_entry('E', "Cannot create archive file: %s\n", gh->archive_file);
- X gh->master_flag &= ~M_AUTO_ARCHIVE;
- X return;
- X }
- X
- X fseek(arc, start, 0);
- X fprintf(arc, "%s%8ld %s\n", arc_header, (long)num, gh->group_name);
- X fseek(arc, (off_t)0, 2);
- X
- X fseek(f, (off_t)0, 0);
- X while ((c = getc(f)) != EOF) putc(c, arc);
- X putc(NL, arc);
- X fclose(arc);
- X}
- X
- Xstatic build_hdr(type)
- Xint type;
- X{
- X register char *name, *subj;
- X int re;
- X
- X db_data.dh_type = type;
- X
- X if (type == DH_SUB_DIGEST) {
- X
- X name = digest.dg_from;
- X subj = digest.dg_subj;
- X
- X db_hdr.dh_lines = digest.dg_lines;
- X
- X db_hdr.dh_hpos = digest.dg_hpos;
- X db_hdr.dh_fpos = (int16)(digest.dg_fpos - db_hdr.dh_hpos);
- X db_hdr.dh_lpos = digest.dg_lpos;
- X
- X db_hdr.dh_date = pack_date(digest.dg_date ? digest.dg_date : news.ng_date);
- X } else {
- X
- X if (!news.ng_from) news.ng_from = news.ng_reply;
- X
- X name = news.ng_from;
- X subj = news.ng_subj;
- X
- X db_hdr.dh_lines = news.ng_lines;
- X
- X db_hdr.dh_hpos = 0;
- X db_hdr.dh_fpos = (int16)(news.ng_fpos);
- X db_hdr.dh_lpos = news.ng_lpos;
- X
- X db_hdr.dh_date = pack_date(news.ng_date);
- X }
- X
- X if (name) {
- X db_hdr.dh_sender_length = pack_name(db_data.dh_sender, name, NAME_LENGTH);
- X } else
- X db_hdr.dh_sender_length = 0;
- X
- X if (type == DH_DIGEST_HEADER) {
- X db_hdr.dh_subject_length = 1;
- X db_data.dh_subject[0] = '@';
- X } else
- X db_hdr.dh_subject_length = 0;
- X
- X db_hdr.dh_subject_length +=
- X pack_subject(db_data.dh_subject + db_hdr.dh_subject_length, subj, &re,
- X DBUF_SIZE);
- X
- X#ifdef COUNT_RE_REFERENCES
- X if (re) re = 0x80;
- X if (news.ng_ref) {
- X for (name = news.ng_ref; *name; name++) {
- X if ((re & 0x7f) == 0x7f) break;
- X if (*name == '<') re++;
- X }
- X }
- X#endif
- X db_hdr.dh_replies = re;
- X
- X if (db_write_art(data) < 0) write_error();
- X}
- X
- X
- Xstatic collect_article(gh, art_num)
- Xregister group_header *gh;
- Xarticle_number art_num;
- X{
- X FILE *art_file;
- X news_header_buffer nhbuf, dgbuf;
- X article_header art_hdr;
- X int mode, count;
- X cross_post_number *cp_ptr;
- X long age;
- X
- X count = 0;
- X
- X db_hdr.dh_number = art_num;
- X
- X /* get article header */
- X
- X art_hdr.a_number = art_num;
- X art_hdr.hpos = (off_t)0;
- X art_hdr.lpos = (off_t)0;
- X art_hdr.flag = 0;
- X
- X mode = FILL_NEWS_HEADER | FILL_OFFSETS | SKIP_HEADER;
- X if ((gh->master_flag & (M_CONTROL | M_NEVER_DIGEST | M_ALWAYS_DIGEST)) == 0)
- X mode |= DIGEST_CHECK;
- X#ifdef NNTP
- X if ((gh->master_flag & M_ALWAYS_DIGEST) == 0)
- X mode |= LAZY_BODY;
- X#endif
- X if ((art_file = open_news_article(&art_hdr, mode, nhbuf, (char *)NULL)) == NULL) {
- X
- X#ifdef NNTP
- X import nntp_failed;
- X
- X if (nntp_failed) {
- X /*
- X * connection to nntp_server is broken
- X * stop collection of articles immediately
- X */
- X return -1;
- X }
- X#endif
- X /*
- X * it is not really necessary to save anything in the data file
- X * we simply use the index file to get the *first* available article
- X */
- X return 0;
- X }
- X
- X if (art_file == (FILE *)1) { /* empty file */
- X if (!ignore_bad_articles) return 0;
- X news.ng_groups = NULL;
- X art_file = NULL;
- X } else
- X if ( max_article_age && /* == 0 if use_nntp */
- X (gh->master_flag & M_INCLUDE_OLD) == 0 &&
- X (age = m_time(art_file)) < max_article_age) {
- X
- X if (remove_bad_articles) unlink(group_path_name);
- X
- X log_entry('O', "%sold article (%ld days): %s/%ld",
- X remove_bad_articles ? "removed " : "",
- X (cur_time() - age) / (24 * 60 * 60),
- X current_group->group_name, (long)art_num);
- X bad_count++;
- X fclose(art_file);
- X return 0;
- X }
- X
- X if (ignore_bad_articles && news.ng_groups == NULL) {
- X char *rem = "";
- X
- X if (!use_nntp && remove_bad_articles) {
- X unlink(group_path_name);
- X rem = "removed ";
- X }
- X
- X log_entry('B', "%sbad article: %s/%ld", rem,
- X current_group->group_name, (long)art_num);
- X if (art_file != NULL) fclose(art_file);
- X bad_count++;
- X return 0;
- X }
- X
- X /* map cross-postings into a list of group numbers */
- X
- X db_hdr.dh_cross_postings = 0;
- X
- X if (gh->master_flag & M_CONTROL) {
- X /* we cannot trust the Newsgroups: line in the control group */
- X /* so we simply ignore it (i.e. use "Newsgroups: control") */
- X goto dont_digest;
- X }
- X
- X if (news.ng_groups) {
- X char *curg, *nextg;
- X group_header *gh1;
- X
- X for (nextg = news.ng_groups, cp_ptr = db_data.dh_cross; *nextg; ) {
- X curg = nextg;
- X
- X if (nextg = strchr(curg, ','))
- X *nextg++ = NUL;
- X else
- X nextg = "";
- X
- X if (strcmp(gh->group_name, curg) == 0)
- X gh1 = gh;
- X else
- X if ((gh1 = lookup(curg)) == NULL) continue;
- X
- X *cp_ptr++ = NETW_CROSS_EXT(gh1->group_num);
- X if (++db_hdr.dh_cross_postings == DBUF_SIZE) break;
- X }
- X }
- X
- X if (db_hdr.dh_cross_postings == 1)
- X db_hdr.dh_cross_postings = 0; /* only current group */
- X
- X if (gh->master_flag & M_NEVER_DIGEST)
- X goto dont_digest;
- X
- X /* split digest */
- X
- X if ((gh->master_flag & M_ALWAYS_DIGEST) || (news.ng_flag & N_DIGEST)) {
- X int any = 0, cont = 1;
- X
- X skip_digest_body(art_file);
- X
- X while (cont && (cont = get_digest_article(art_file, dgbuf)) >= 0) {
- X
- X if (any == 0) {
- X build_hdr(DH_DIGEST_HEADER); /* write DIGEST_HEADER */
- X count++;
- X db_hdr.dh_cross_postings = 0; /* no cross post in sub */
- X any++;
- X }
- X build_hdr(DH_SUB_DIGEST); /* write SUB_DIGEST */
- X count++;
- X }
- X
- X if (any) goto finish;
- X }
- X
- X /* not a digest */
- X
- X dont_digest:
- X
- X build_hdr(DH_NORMAL); /* normal article */
- X count++;
- X
- Xfinish:
- X
- X if (gh->master_flag & M_AUTO_ARCHIVE)
- X do_auto_archive(gh, art_file, art_num);
- X
- X fclose(art_file);
- X
- X return count;
- X}
- X
- X
- X/*
- X * Collect unread articles in current group
- X *
- X * On entry, init_group has been called to setup the proper environment
- X */
- X
- Xstatic long collect_group(gh)
- Xregister group_header *gh;
- X{
- X long article_count, temp, obad;
- X article_number start_collect;
- X
- X if (gh->last_db_article == 0) {
- X gh->first_db_article = gh->first_a_article;
- X gh->last_db_article = gh->first_db_article - 1;
- X }
- X
- X if (gh->last_db_article >= gh->last_a_article) return 0;
- X
- X if (gh->index_write_offset) {
- X ix = open_data_file(gh, 'x', OPEN_UPDATE|MUST_EXIST);
- X fseek(ix, gh->index_write_offset, 0);
- X } else
- X ix = open_data_file(gh, 'x', OPEN_CREATE|MUST_EXIST);
- X
- X if (gh->data_write_offset) {
- X data = open_data_file(gh, 'd', OPEN_UPDATE|MUST_EXIST);
- X fseek(data, gh->data_write_offset, 0);
- X } else
- X data = open_data_file(gh, 'd', OPEN_CREATE|MUST_EXIST);
- X
- X article_count = 0;
- X start_collect = gh->last_db_article+1;
- X
- X if (debug_mode) {
- X printf("\t\t%s (%ld..%ld)\r",
- X gh->group_name, start_collect, gh->last_a_article);
- X fl;
- X }
- X bad_count = obad = 0;
- X
- X while (gh->last_db_article < gh->last_a_article) {
- X if (s_hangup) break;
- X gh->last_db_article++;
- X if (debug_mode) {
- X printf("\r%ld", gh->last_db_article);
- X if (obad != bad_count) printf("\t%ld", bad_count);
- X obad = bad_count;
- X fl;
- X }
- X gh->data_write_offset = ftell(data);
- X#ifdef NNTP
- X gh->index_write_offset = ftell(ix);
- X#endif
- X temp = collect_article(gh, gh->last_db_article);
- X#ifdef NNTP
- X if (temp < 0) {
- X /* connection failed, current article is not collected */
- X gh->last_db_article--;
- X article_count = -1;
- X goto out;
- X }
- X#endif
- X#ifndef RENUMBER_DANGER
- X if (temp == 0 && gh->data_write_offset == (off_t)0) {
- X gh->first_db_article = gh->last_db_article + 1;
- X continue;
- X }
- X#endif
- X if (!db_write_offset(ix, &(gh->data_write_offset)))
- X write_error();
- X article_count += temp;
- X }
- X
- X if (start_collect < gh->first_db_article)
- X start_collect = gh->first_db_article;
- X
- X if (trace && start_collect <= gh->last_db_article)
- X log_entry('T', "Col %s (%d to %d) %d",
- X gh->group_name,
- X start_collect, gh->last_db_article,
- X article_count);
- X
- X if (debug_mode)
- X printf("\nCol %s (%d to %d) %d",
- X gh->group_name,
- X start_collect, gh->last_db_article,
- X article_count);
- X
- X gh->data_write_offset = ftell(data);
- X gh->index_write_offset = ftell(ix);
- X
- X out:
- X fclose(data);
- X fclose(ix);
- X
- X if (debug_mode) putchar(NL);
- X
- X return article_count;
- X}
- X
- X
- Xdo_collect()
- X{
- X register group_header *gh;
- X long col_article_count, temp;
- X int col_group_count;
- X time_t start_time;
- X
- X start_time = cur_time();
- X col_article_count = col_group_count = 0;
- X current_group = NULL; /* for init_group */
- X temp = 0;
- X
- X Loop_Groups_Header(gh) {
- X if (s_hangup) {
- X temp = -1;
- X break;
- X }
- X
- X if (gh->master_flag & M_IGNORE_GROUP) continue;
- X
- X if (gh->master_flag & M_MUST_CLEAN)
- X clean_group(gh);
- X
- X if (gh->last_db_article == gh->last_a_article) {
- X if (gh->master_flag & M_BLOCKED) goto unblock_group;
- X continue;
- X }
- X
- X if (!init_group(gh)) {
- X if ((gh->master_flag & M_NO_DIRECTORY) == 0) {
- X log_entry('R', "%s: no directory", gh->group_name);
- X gh->master_flag |= M_NO_DIRECTORY;
- X }
- X gh->last_db_article = gh->last_a_article;
- X gh->first_db_article = gh->last_a_article; /* OBS: not first */
- X gh->master_flag &= ~(M_EXPIRE | M_BLOCKED);
- X db_write_group(gh);
- X continue;
- X }
- X
- X if (gh->master_flag & M_NO_DIRECTORY) {
- X /* The directory has been created now */
- X gh->master_flag &= ~M_NO_DIRECTORY;
- X clean_group(gh);
- X }
- X
- X temp = collect_group(gh);
- X#ifdef NNTP
- X if (temp < 0) {
- X /* connection broken */
- X gh->master_flag &= ~M_EXPIRE; /* remains blocked */
- X db_write_group(gh);
- X break;
- X }
- X#endif
- X if (temp > 0) {
- X col_article_count += temp;
- X col_group_count++;
- X }
- X
- X unblock_group:
- X if (temp > 0 || (gh->master_flag & M_BLOCKED)) {
- X gh->master_flag &= ~(M_EXPIRE | M_BLOCKED);
- X db_write_group(gh);
- X }
- X }
- X
- X if (col_article_count > 0)
- X log_entry('C', "Collect: %ld art, %d gr, %ld s",
- X col_article_count, col_group_count,
- X cur_time() - start_time);
- X
- X return temp >= 0;
- X}
- END_OF_FILE
- if test 11227 -ne `wc -c <'collect.c'`; then
- echo shar: \"'collect.c'\" unpacked with wrong size!
- fi
- # end of 'collect.c'
- fi
- if test -f 'doc/NEWS-6.4' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'doc/NEWS-6.4'\"
- else
- echo shar: Extracting \"'doc/NEWS-6.4'\" \(12220 characters\)
- sed "s/^X//" >'doc/NEWS-6.4' <<'END_OF_FILE'
- XNew features in release 6.4 (compared to release 6.3.10):
- X---------------------------------------------------------
- X
- XIncompatible changes:
- X Regular expressions in kill file are now CASE INSENSITIVE by default.
- X - must use '/=' instead of '/' to get 6.3 behaviour.
- X
- XMajor improvements:
- X Uses standard .newsrc
- X Individual articles can be left unread between invocations.
- X Even individual digest sub-articles can remain unread!!!
- X Articles can also remain "selected" between invocations.
- X New faster expiration in database
- X Unsubscribed groups can be omitted from .newsrc.
- X More flexible and configureable installation.
- X Locking to avoid simultaneous use of nn.
- X Global database locking.
- X Optional accounting, quota, and authorization possibilities.
- X Presentation sequence can now be (partially) based on .newsrc
- X Nnmaster can automatically archive all new articles in selected groups.
- X Related groups can be merged into one group when shown to the user.
- X Menus are now sorted in "subject age" order.
- X Map command can now include definition of anonymous macroes.
- X Auto kill/select possibilities significantly expanded.
- X
- X
- XLevel of program changes (from user's point of view):
- X *** => new program, ** => major changes/rewrite, * => minor changes
- X
- X ** nn(1) The news reader program
- X *** nnacct(1m) Accounting, quota, and access management
- X * nnadmin(1m) The administration program (link to nn)
- X * nncheck(1) Check for unread articles (link to nn)
- X ** nngoback(1) Mark older articles as unread (link to nn)
- X *** nngrab(1) Faster keyword search
- X ** nngrep(1) Grep for news groups (link to nn)
- X ** nnmaster(8) Database manager
- X *** nnpost(1) Standalone posting program (link to nn).
- X *** nnspew(8) Subject list maintenance
- X ** nntidy(1) Cleans up the rc file (link to nn)
- X *** nnstats(1m) Collection and expiration statistics
- X * nnusage(1) Show usage statistics
- X
- X
- XChanges in standard key mappings:
- X---------------------------------
- X
- Xselection mode:
- X CR -> continue-no-mark (IMPORTANT!)
- X J -> junk-articles
- X L -> leave-next
- X " -> layout
- X
- Xreading mode:
- X L -> leave-next
- X
- X
- XNew key commands:
- X-----------------
- X
- Xcontinue-no-mark (CR)
- Xjunk-articles (J)
- Xleave-next (L)
- X
- X
- XNew control structures in init file
- X-----------------------------------
- X
- Xon host ... end Execute only on specified hosts
- Xon term ... end Execute only on specified terminals
- Xon slow ... end Execute only at slow speed
- Xon fast ... end Execute only at higher speeds (>2400)
- Xsave-files ... end Specify default save files for groups
- X without messing up the sequence.
- X
- X:bug send a bug report
- X:cost show current accounting figures
- X:local VARIABLE [VALUE] make VARIABLE local to current group [and set to VALUE]
- X:rmail read incoming mail (no update)
- X:show rc [GROUP] show (current) GROUPS .newsrc entry
- X
- XNew menu sorting methods
- X------------------------
- X
- X:sort sender
- X:sort lexical
- X:sort subject (will order subjects according to age of first article)
- X
- X
- XNew variables
- X-------------
- X
- Xappend-signature-mail Explicitly append .signature to outgoing mail
- Xappend-signature-post Explicitly append .signature to posted articles
- Xattributes Article attribute symbols
- Xauto-junk-seen Automatically mark seen articles read
- Xauto-preview-mode Enter preview mode when selecting an article on menu
- Xbackup (new semantics) Keep backup of rc file (-B)
- Xbackup-suffix STR String to append to backup file names (.bak)
- Xbug-report-address Mail address for the :bug command
- Xcase-fold-search String and pattern matching is case independent (! -i)
- Xcollapse-subject Offset at which long subjects are compressed
- Xconfirm-auto-quit User must confirm quit after reading last group
- Xconfirm-create User must confirm creation of new files
- Xconfirm-entry User must confirm entry to groups
- Xconfirm-entry-limit N - confirm only for groups with more than N unread art.
- Xconfirm-junk-seen Ask for confirmation before marking seen articles read
- Xcross-filter-seq Show cross posted articles in first group in sequence
- Xdata-bits N Screen output is 7 or 8 bits
- Xdecode-skip-prefix N Automatically unshar uuencoded articles if N>0
- Xedit-patch-command Allow user to edit command used by :patch before exec
- Xedit-print-command Allow user to edit command used by :print before exec
- Xedit-unshar-command Allow user to edit command used by :unshar before exec
- Xedit-response-check Don't send articles if they are not edited.
- Xeditor CMD Use speficied editor instead of $EDITOR
- Xentry-report-limit N Give entry report for groups with >N unread articles
- Xexpired-message-delay N Wait for N seconds after telling article is expired.
- Xflush-typeahead Flush typeahead before reading each command
- Xinclude-full-header M command includes full header in mailed articles.
- Xkeep-unsubscribed Keep unsubscribed groups in .newsrc
- Xmailer CMD Use CMD to send outgoing mail
- Xmailer-pipe-input 'mailer' reads standard input/takes file argument
- Xmmdf-format Folders are written in MMDF format
- Xnew-group-action N Specifies how NEW groups are handles -- see :man
- Xnewsrc FILE Specify alternative .newsrc file (new semantics)
- Xnntp-cache-dir DIR Alternative directory for nntp cache files
- Xnntp-cache-size N Max number of different files in cache.
- Xorig-to-include-mask N Specifies which header fields are placed in Orig-To:
- Xpreview-continuation N Specifies what to do after preview of one article
- Xpreview-mark-read Previewing an article marks it read
- Xquery-signature Ask for confirmation before appending .signature
- Xquick-count Use quick method to count unread articles in .newsrc
- Xre-layout N Presentation of Re: prefixes on menu subjects
- Xrepeat-group-query Cause 'nn -g' to repeat group query (-r)
- Xreport-cost Report cost of session on exit
- Xresponse-check-pause N Wait N seconds after mailing/posting for error check
- Xresponse-default-answer STR Default answer to action prompt
- Xretain-seen-status Retain articles' seen status between invocations
- Xretry-on-error N Retry N times if open of article fails
- Xsave-counter-offset First value of save counter
- Xscroll-clear-page Scrolling clears page before drawing next page
- Xselect-on-sender Should = command on menu match on sender or subject
- Xselect-leave-next Ask to mark leave-next articles selected on entry
- Xslow-mode Minimize screen output
- Xslow-speed SPEED 'on slow' clause is true for this and lower speeds
- Xsort-mode N Default sort mode for menus and :sort command
- Xspell-checker CMD Spelling checker for edited messages (one arg)
- Xsubject-match-limit N Treat subjects matching in N characters as identical
- Xsubject-match-offset N Skip N characters of subjects before comparison
- Xsubject-match-parts Treat subjects matching upto first digit as idential
- Xsuggest-default-save Show default save file name on prompt line.
- Xtidy-newsrc Automatically remove garbage from .newsrc
- Xupdate-frequency N Write .newsrc for every N groups
- Xuse-selections Use select file
- Xvisible-bell Use visible bell if defined in termcap/terminfo
- Xwrap-header-margin Fold long header lines over multiple lines
- X
- X
- XNew options:
- X------------
- X
- Xnnmaster: -G -l [lock message] -i -H -k -O -X
- X -I [limit] -D [level] -Q [[!]group]...
- Xnntidy: -N -Q -v -a -c -i -r -s -u
- Xnngrep: -a -n -p -r -s -u -l
- Xnncheck: -c [groups]...
- Xnngoback: -v -i [groups]...
- Xnn: -Ifiles -nsender -i
- X
- Xnnadmin changes
- X---------------
- X
- XE)xpire and I)nitialize commands now requires confirmation also when
- Xcalled from command line:
- X nnadmin =EYW -- request expire (from cron)
- X nnadmin IY -- request rebuild
- X
- XZ)ap in GROUP menu -- will call rmgroup to remove group.
- XV)alidation can now be run from nn's :admin command.
- XD)ump entry on master menu.
- X! - will fork subshell on all menus.
- X
- X
- XOther changes (highlights):
- X---------------------------
- X
- XNOTICE: nn no longer relies on the `min' field in the active file to
- X detect expire. So there is no need to run the `upact' program
- X with Cnews anymore.
- X
- Xnntidy, nngoback and nngrep are now integrated into nn giving them a
- Xmuch greater flexibility, e.g. you can go back on individual groups or
- Xhierarchies (interactively).
- X
- Xnnmaster can now ignore and optionally remove badly formed and
- Xout-dated articles in the news spool directory (not with NNTP).
- XThis can give more accurate numbers of unread articles, and also
- Xsmaller databases.
- X
- XIndividual groups and group hierarchies can now be permanently
- Xexcluded from the database, and per-group flags can be permanantly set
- Xin the GROUPS file. Groups can be automatically archived and archive
- Xis directly available from nn. Some possibilities are:
- X
- X R recollect all articles on every scan
- X X ignore group
- X D always try to split articles as digests
- X N never attempt to digest articles
- X >file append all new articles to file
- X
- X'*' part counter can now be specified anywhere in save file names.
- XSeveral roblems with `$N' has been fixed.
- X
- XDefault save file names are now expanded ($L/$F/$G) when shown.
- X
- XRC, RC:nnn, and RC:string forms can now be specified in the
- Xpresentation sequence to use all or part of .newsrc as the
- Xgroup order information when building presentation sequence.
- X
- XThe kill file can now contain entries which "trigger" on matching more
- Xthan one field or value, and it may also contain "kill unless" entries.
- XFor example, to kill all articles NOT from ME on subject "XY.*Z:" :
- X group:~n=&s/:ME:XY.*Z\:
- X(these complex entries must be entered manually into the kill file).
- X
- XKill entries can work for a set of groups specified with a regular
- Xexpression, e.g. /^news\.*:+n=:Kim F. Storm
- X
- XTimezone is now considered when sorting articles on date.
- X
- XSingle character arrow keys are no longer recognized as arrow keys if
- Xthey send the same code as "erase" "kill" "interrupt" CR or NL!!!
- X
- XNow parses "n", "x", and "=group" codes in the active file and handles
- Xgroups accordingly.
- X
- XUnsubscribed groups can now be omitted from .newsrc provided
- Xnew-group-action is set appropriately. It uses per-group creation
- Xtime stamps saved either in a .nn/LAST file or an rn compatible
- X.rnlast file.
- X
- Xnnmaster will now dynamically expand the MASTER file, and thus never
- Xrun out of "free group slots".
- X
- X"q" and "Q" can now be used in addition to ^G and "interrupt" to
- Xbreak out of multi-page listings (hit any key to continue).
- X
- Xnn -a0 will now allow you to (U)nsubscribe to a group and (r)ead a
- Xgroup directly. It also accepts a (q)uit answer.
- X
- XReturn value when saving through a pipe is now checked and an error
- Xmessage is given if the command failed.
- X
- XMultiple, alternative init files can now be specified to nn via the -I
- Xoption:
- X nn -Ia,,b First read a, then global init file, then b.
- X nn -I,init This is the default (read global, then local file)
- X
- X"on term" can now match several terminal types, e.g. "on term t1 t2 t9"
- X
- XG command now acts "reasonnable" on empty reply to the "number of
- X(extra) articles" prompt:
- X If goto another group with unread articles => j
- X If goto another group without unread articles => a
- X If goto same group with more unread articles => u
- X If goto same group without more unread articles => a
- X
- XThe G command can now search on sender as well as subject (and both).
- X
- XCross postings are now eliminated according to the presentation
- Xsequence rather than the Newsgroups: line by default. Here is what
- XWayne Davison has said about the new method:
- X
- X Now that I have been using "tn"s article selector and see the same
- X subjects appear in a second group, I agree with you totally that
- X your new method of handling cross-posted articles is the right way
- X to go. It gets especially annoying when I have marked a
- X cross-posted article as unread in one group and encounter it in a
- X second group -- I must remember to mark it unread again or it will
- X be marked as read in both groups. Just thought you might like to
- X know.
- X
- X
- XFour new "selectors" in group sequence. Neither of these include
- Xanything directly in the sequence, but they will EXCLUDE groups from
- Xthe sequence:
- X !:X groups excludes groups not in .newsrc, e.g. "!:X alt*"
- X will exclude all "alt" groups not found in .newsrc.
- X !:O groups exclude groups unless they are new, e.g.
- X "!:O bionet*" will ignore OLD bionet groups even
- X when they occur in .newsrc.
- X !:U groups exclude unsubscribed groups.
- X !:N groups exclude new groups.
- X
- X
- X$(VAR) is now expanded in file names (VAR is an environment variable).
- X
- XAnd lots more if you upgrade from 6.3.0!!!
- END_OF_FILE
- if test 12220 -ne `wc -c <'doc/NEWS-6.4'`; then
- echo shar: \"'doc/NEWS-6.4'\" unpacked with wrong size!
- fi
- # end of 'doc/NEWS-6.4'
- fi
- if test -f 'doc/NNTP' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'doc/NNTP'\"
- else
- echo shar: Extracting \"'doc/NNTP'\" \(12793 characters\)
- sed "s/^X//" >'doc/NNTP' <<'END_OF_FILE'
- X NNTP SUPPORT
- X ------------
- X
- XThis file describes the NNTP support available in nn release 6.4. The
- XNNTP support was implemented by Rene' Seindal, seindal@diku.dk.
- X
- X
- X PREREQUISITES
- X -------------
- X
- XFirst of all, you need read-access to an NNTP-server, and if you want
- Xto post, the server must allow that.
- X
- XIf you have news on one of your systems, and want to run an NNTP
- Xserver on that system to feed other local systems, you need to get and
- Xinstall the nntp-1.5 distribution with at least patches 1-3 (I think
- Xpatch 8 is the latest). It is available from several ftp-sites in the
- XUSA. It is also available on freja.diku.dk (ip 129.142.96.1).
- X
- XHowever, just to run nn on you local system with or without NNTP, you
- Xdon't need anything besides the nn 6.4 distribution!!
- X
- XThe necessary modules to access a remote NNTP server is an integrated
- Xpart of nn, so if you specify to use NNTP, the necessary code is
- Xautomatically included.
- X
- XA recent version of the `mini-inews' program which is required to post
- Xarticles via an NNTP server is also included for your convenience.
- XSee the INEWS section below.
- X
- X HOW IT WORKS
- X ------------
- X
- XNNTP is supported both in nn and nnmaster. When NNTP is used, the
- Xdatabase with the header information used by nn is still maintained on
- Xthe local system (because NNTP does not know about the nn database
- X(yet?)).
- X
- XWhen the master is set up to use NNTP, it will connect to the NNTP-
- Xserver in each iteration of the collection (the interval set with -r),
- Xget a copy of the active file, and incorporate the new articles into the
- Xdatabase. To do this, the master will temporarily transfer one article
- Xat a time from the NNTP-server to the local system.
- X
- XWhen the articles are read with nn, it will use the local database to
- Xpresent the menus, and fetch the articles from the NNTP-server as they
- Xare requested by the user. It will connect to the NNTP server the first
- Xtime it is necessary to fetch an article.
- X
- XNeither nnmaster, nor nn will use NNTP if they run on the NNTP-server
- Xitself (they will directly access the news files).
- X
- XBoth nn and nnmaster access the server in reading mode. The master and
- Xall client MUST use the same server at all times, since the local
- Xdatabase contains article numbers, that are only unique for each
- XNNTP-server.
- X
- X
- X SHARING THE DATABASE
- X --------------------
- X
- XYou must also decide whether you want to share the database between your
- Xlocal news clients, and how you are going to do it.
- X
- XThe database will take up some disk space, normally about 1Mb per 10.000
- Xarticles. There are several ways to manage this space.
- X
- XThis simplest solution, is to let each client run it own master, i.e.,
- Xhave its own database. This means, of course, no sharing.
- X
- XAlternatively, one host can run the master, and distribute the database
- Xto the others via e.g., rdist. This doesn't save disk space, but saves
- Xload on the NNTP-server.
- X
- XLast, the database can be shared with NFS/RFS (see the description of
- XNETWORK_DATABASE in the config.h file).
- X
- XThe possibility of making a `nndb-server' stands open. It could be
- Xrealized either as a separate server, running under inetd, or it could
- Xbe incorporated into nntpd. It has not been implemented, but might be
- Xpart of a future release (any volunteers?).
- X
- X
- X CONFIGURATION
- X -------------
- X
- XTo use NNTP in nn, you must edit the relevant parts of config.h:
- X
- XNNTP
- X You enable the use of NNTP by defining the macro NNTP.
- X
- XNNTP_SERVER
- X Both the master and the clients will look up their NNTP-server
- X in the file given by the macro NNTP_SERVER. If the name is not
- X an absolute path name, it is taken to be relative to
- X LIB_DIRECTORY.
- X
- X The format of the file is compatible with the one used in
- X clientlib.c in the nntp-1.5 distribution, i.e., the first
- X non-blank line, not starting with '#' is taken to be the name of
- X the NNTP-server. This file MUST be present, and must contain a
- X valid host name.
- X
- XNNTP_POST
- X If you use the NNTP based inews (part on the NNTP distribution)
- X and you have hosts that are not allowed to post to the NNTP
- X server, you should defined this. It will make nn check at
- X connect time whether the NNTP server allows postings, and reject
- X all attempts to post, if the server disallows posting. If you
- X do not define this, users will be allowed to post by nn, but the
- X posting will eventually fail.
- X
- X Again, this parameter is only relevant, if you use the NNTP
- X based inews, and have hosts that are not allowed to post.
- X
- XNNTP_MINI_INEWS_HEADER
- X According to RFC 977, the mini-inews that comes with nntp
- X requires that the articles it receives contain a complete
- X header including Message-ID, Date, and Path fields (which the
- X normal inews generates itself). I consider this to be a bug
- X in the RFC, and maybe some (future?) versions of mini-inews
- X will provide these fields. However, if you use mini-inews for
- X postings and your version of mini-inews does not generate
- X these headers, you should define NNTP_MINI_INEWS_HEADER in
- X config.h. Notice that the Message-ID and Path may be less
- X than perfect (but the Message-ID should be unique)!
- X
- X
- XNEWS_LIB_DIRECTORY & INEWS
- X If either is defined, they specify the destination of the
- X mini-inews program when installed below with INEWS being used
- X if both are defined. If neither is defined, it will be
- X installed in /usr/lib/news/inews.
- X
- X
- X
- X TUNING
- X ------
- X
- XBoth the server and each client maintains a cache of recently accessed
- Xarticles, to minimize communication with the server (mainly to avoid
- Xfetching large digests continuously). The master needs the cache when
- Xit splits digests, and the clients need it, because nn has a tendency to
- Xreopen the articles several times.
- X
- XThe master's cache is kept in LIB_DIRECTORY, and each client's cache are
- Xkept in the users .nn directory. The constant NNTPCACHE (defined in
- Xnntp.c but can be redefined in config.h) defines the size of the cache,
- Xwhose optimal size depends on the amount of news kept on line on the
- XNNTP-server. Values of 5-10 gives reasonable results. The effect is
- Xmost striking when reading digested news.
- X
- XThe location and size of the cache can also be changed on a per-user
- Xbasis via the related nntp- variables (see nn.1).
- X
- X
- X INSTALLATION
- X ------------
- X
- XMaking and installing nn using NNTP does not differ from a non-NNTP nn
- Xinstallation, except for the differences in the configuration and the
- Xneed to specify the NNTP server in the NNTP_SERVER file.
- X
- XNotice however, that the NNTP_SERVER file must be properly initialized
- Xbefore doing the 'make initdb'.
- X
- XIf something goes wrong in the initialization of the database, you will
- Xhave to run 'nnmaster -I' again by hand.
- X
- X
- X INEWS
- X -----
- X
- XIf you want to post news via the NNTP server, you will need to run a
- Xprogram named `(mini-)inews' which is included in the normal NNTP
- Xdistribution. However, since this is the only part of the NNTP you
- Xneed to run nn, a recent version (1.5.7) of the mini-inews program is
- Xincluded with nn in the inews/ directory.
- X
- XIf you already have installed and maintain mini-inews on your system,
- Xyou should not use the version that comes with nn - it would just be
- Xextra unnecessary work.
- X
- XHowever, if you don't run mini-inews already, using the version that
- Xcomes with nn will be somewhat simpler to configure, because it takes
- Xadvantage of the definitions you have already made for nn in config.h.
- X
- XThanks to Steve Simmons who contributed the simplified inews
- Xconfiguration (which I took the freedom to simplify even further).
- X
- XTo configure and install mini-inews, all you should need to do is
- X(everything must be done with inews/ as current working directory):
- X
- X $ cd inews
- X $ edit conf.h -- modify as described in the file
- X $ make
- X
- XIf things work, type:
- X
- X $ su
- X # make install
- X
- XAs far as I know, NNTP_MINI_INEWS_HEADER needs to be defined in
- Xnn's config.h for nn to work with this mini-inews version.
- X
- XSee the files inews/README.NN and inews/README for further information.
- X
- X
- X ERROR HANDLING
- X --------------
- X
- XThe handling of errors have been improved since the initial release.
- X
- XThe master will handle most errors by closing the connection, and
- Xreturning to the main loop. All errors in the master are logged, with
- Xa code of `N,' so they can be inspected with the `n' command in
- Xnnadmin's Log menu.
- X
- XA few errors are considere fatal. If any of these occur operation will
- Xbe discontinued. These errors are such as failure to find the NNTP
- Xserver, failure to find the NNTP service, and responses from the NNTP
- Xserver in the 500 range (ill-formed requests, access denied, ...)
- X
- XNNTP server timeouts are handled specially. If the NNTP server times
- Xout, both nn and the master will attempt to restart it (by connecting
- Xagain). This shouldn't happen in the master (which won't leave sockets
- Xidle for that long), but it can easily happen in nn, if it is left
- Xsuspended for too long. If the server responds with code 400 (Service
- Xdiscontinued), a reconnect is also tried.
- X
- X
- X PROBLEMS
- X --------
- X
- XI am not certain what should happen if the server sends back responses
- Xin the 1xx range. I do not know whether a NNTP server is allowed to
- Xreturn one of these responses on its own initiative. If it is, nn
- Xshould probably ignore (or display) the messages. Currently, nothing is
- Xdone to treat these responses in any way.
- X
- XI have seen a strange thing happen to the master, which I have not been
- Xable to reproduce. The master ran on a Sun-4 running SunOS 4.0, and the
- XNNTP server was a VAX 785 running MORE/bsd. The NNTP software was
- Xversion 1.5.3. The master was stuck in a read from the NNTP server. A
- Xnetstat on the Sun show an established connection to nntpd on the Vax,
- Xbut a netstat on the Vasx did not show any NNTP connections. There was
- Xno nntpd running, and no messages on the console indicating any
- Xfailures.
- X
- X[ It is now known that this problem is related to the socket not
- X having the KEEP ALIVE flag set, but I have not got the necessary
- X patches to fix it, ++Kim ]
- X
- X
- XIf you want to debug the nntp connection, you can run the nnmaster
- Xwith the option -D2 (or -D3 which also turns on the normal -D verbose
- Xoutput). In the nn client, you can turn on the nntp-debug variable in
- Xthe init file.
- X
- XThe debug output from nnmaster will be placed in $TMP/nnmaster.log
- Xwhile the output in the client will appear on the message line.
- X
- X
- X POSSIBLE EXTENTIONS TO THE NNTP SERVER
- X --------------------------------------
- X
- XThe new expire method used in release 6.4 is very efficient on local
- Xsystems, because it will just read the spool directories to get a list
- Xof available articles in each group.
- X
- XHowever, with nntp, the only way I know of to get a list of available
- Xarticles in a group with nntp is the XHDR request. However, this will
- Xopen every article in the group to extract the desired field, but the
- Xonly thing I am interested in is the article number itself.
- X
- XSo I suggest to add a LISTGROUP request to the NNTP server to return
- Xthe equivalent of
- X ls $GROUPDIR | sed -n '/^[0-9][0-9]*$/p'
- X(in any order - nnmaster will sort the list itself).
- X
- XCurrently nnmaster will test whether this request works before using
- Xthe XHDR request, so no changes to nnmaster will be required to take
- Xadvantage of such a fix.
- X
- X
- XAnother possible performance increase would be if there was a request
- Xto get the current modification time of the ACTIVE file. This is the
- Xcheck nnmaster will do to see if there might be work to do on a local
- Xsystem, but with NNTP it has to read the active file from the server
- Xand compare it to a local copy to determine whether there is work to
- Xdo. A simple ACTIVESTAT request returning the active file's age and
- Xsize would fix this.
- X
- XCurrently nnmaster is not prepared to use such a request, but it would
- Xbe easy to add.
- X
- X
- X ALTERNATIVES
- X ------------
- X
- XAlternative implementations can be conceived, especially in the master.
- XThe master normally collects articles by rereading the active file,
- Xlooking for changed article numbers. For each group with new articles,
- Xit reads the new articles and adds them to the database. This scheme
- Xhas been kept in the NNTP-based master, to keep the changes at a
- Xminimum.
- X
- XAn alternative solution could be to use NEWNEWS to get a list of new
- Xarticles since last collect, and fetch each article in sequence. The
- Xnewsgroups and article numbers within each group could then be found in
- Xthe Xref: field. This would probably improve efficiency, since the
- Xmaster would then generate fewer failing requests (for non-existent
- Xarticles), and it would only read cross-posted articles once. This
- Xsolution would, however, require some surgery on the current structure
- Xof the masters main loop.
- X
- XSuggestions and improvements are very much welcome. Send your ideas or
- Xcontributions to nn-bugs@dkuug.dk.
- END_OF_FILE
- if test 12793 -ne `wc -c <'doc/NNTP'`; then
- echo shar: \"'doc/NNTP'\" unpacked with wrong size!
- fi
- # end of 'doc/NNTP'
- fi
- if test -f 'inews/clientlib.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'inews/clientlib.c'\"
- else
- echo shar: Extracting \"'inews/clientlib.c'\" \(11231 characters\)
- sed "s/^X//" >'inews/clientlib.c' <<'END_OF_FILE'
- X#ifndef lint
- Xstatic char *sccsid = "@(#)clientlib.c 1.11 (Berkeley) 10/27/89";
- X#endif
- X
- X/*
- X * NNTP client routines.
- X */
- X
- X/*
- X * Include configuration parameters only if we're made in the nntp tree.
- X */
- X
- X#ifdef FOR_NN
- X#include "conf.h"
- X#endif
- X
- X#ifdef NNTPSRC
- X#include "../config.h"
- X#endif NNTPSRC
- X
- X#include <stdio.h>
- X#ifndef FOR_NN
- X#include <sys/types.h>
- X#endif
- X#include <sys/socket.h>
- X#include <netinet/in.h>
- X#ifndef EXCELAN
- X# include <netdb.h>
- X#endif not EXCELAN
- X
- X#ifndef FOR_NN
- X#ifdef USG
- X# define index strchr
- X#endif USG
- X#endif
- X
- X#ifdef EXCELAN
- X# define IPPORT_NNTP 119
- X#endif
- X
- X#ifdef DECNET
- X#include <netdnet/dn.h>
- X#include <netdnet/dnetdb.h>
- X#endif DECNET
- X
- X#include "nntp.h"
- X
- XFILE *ser_rd_fp = NULL;
- XFILE *ser_wr_fp = NULL;
- X
- X/*
- X * getserverbyfile Get the name of a server from a named file.
- X * Handle white space and comments.
- X * Use NNTPSERVER environment variable if set.
- X *
- X * Parameters: "file" is the name of the file to read.
- X *
- X * Returns: Pointer to static data area containing the
- X * first non-ws/comment line in the file.
- X * NULL on error (or lack of entry in file).
- X *
- X * Side effects: None.
- X */
- X
- Xchar *
- Xgetserverbyfile(file)
- Xchar *file;
- X{
- X register FILE *fp;
- X register char *cp;
- X static char buf[256];
- X char *index();
- X char *getenv();
- X char *strcpy();
- X
- X if (cp = getenv("NNTPSERVER")) {
- X (void) strcpy(buf, cp);
- X return (buf);
- X }
- X
- X if (file == NULL)
- X return (NULL);
- X
- X fp = fopen(file, "r");
- X if (fp == NULL)
- X return (NULL);
- X
- X while (fgets(buf, sizeof (buf), fp) != NULL) {
- X if (*buf == '\n' || *buf == '#')
- X continue;
- X cp = index(buf, '\n');
- X if (cp)
- X *cp = '\0';
- X (void) fclose(fp);
- X return (buf);
- X }
- X
- X (void) fclose(fp);
- X return (NULL); /* No entry */
- X}
- X
- X
- X/*
- X * server_init Get a connection to the remote news server.
- X *
- X * Parameters: "machine" is the machine to connect to.
- X *
- X * Returns: -1 on error
- X * server's initial response code on success.
- X *
- X * Side effects: Connects to server.
- X * "ser_rd_fp" and "ser_wr_fp" are fp's
- X * for reading and writing to server.
- X */
- X
- Xserver_init(machine)
- Xchar *machine;
- X{
- X int sockt_rd, sockt_wr;
- X char line[256];
- X char *index();
- X#ifdef DECNET
- X char *cp;
- X
- X cp = index(machine, ':');
- X
- X if (cp && cp[1] == ':') {
- X *cp = '\0';
- X sockt_rd = get_dnet_socket(machine);
- X } else
- X sockt_rd = get_tcp_socket(machine);
- X#else
- X sockt_rd = get_tcp_socket(machine);
- X#endif
- X
- X if (sockt_rd < 0)
- X return (-1);
- X
- X /*
- X * Now we'll make file pointers (i.e., buffered I/O) out of
- X * the socket file descriptor. Note that we can't just
- X * open a fp for reading and writing -- we have to open
- X * up two separate fp's, one for reading, one for writing.
- X */
- X
- X if ((ser_rd_fp = fdopen(sockt_rd, "r")) == NULL) {
- X perror("server_init: fdopen #1");
- X return (-1);
- X }
- X
- X sockt_wr = dup(sockt_rd);
- X if ((ser_wr_fp = fdopen(sockt_wr, "w")) == NULL) {
- X perror("server_init: fdopen #2");
- X ser_rd_fp = NULL; /* from above */
- X return (-1);
- X }
- X
- X /* Now get the server's signon message */
- X
- X (void) get_server(line, sizeof(line));
- X return (atoi(line));
- X}
- X
- X
- X/*
- X * get_tcp_socket -- get us a socket connected to the news server.
- X *
- X * Parameters: "machine" is the machine the server is running on.
- X *
- X * Returns: Socket connected to the news server if
- X * all is ok, else -1 on error.
- X *
- X * Side effects: Connects to server.
- X *
- X * Errors: Printed via perror.
- X */
- X
- Xget_tcp_socket(machine)
- Xchar *machine;
- X{
- X int s;
- X struct sockaddr_in sin;
- X#ifndef EXCELAN
- X struct servent *getservbyname(), *sp;
- X struct hostent *gethostbyname(), *hp;
- X#ifdef h_addr
- X int x = 0;
- X register char **cp;
- X#endif h_addr
- X
- X if ((sp = getservbyname("nntp", "tcp")) == NULL) {
- X fprintf(stderr, "nntp/tcp: Unknown service.\n");
- X return (-1);
- X }
- X
- X /*
- X * Name resolution doesn't quite go as far as it should. Take things
- X * one stage further to allow nnn.nnn.nnn.nnn addresses if all else
- X * fails.
- X */
- X if( (hp = gethostbyname( machine ) ) == NULL ) {
- X unsigned long inet_addr();
- X static struct hostent def;
- X static struct in_addr defaddr;
- X static char *alist[1];
- X static char namebuf[ 256 ];
- X defaddr.s_addr = inet_addr( machine );
- X if( defaddr.s_addr != -1 ) {
- X strcpy( namebuf, machine );
- X def.h_name = namebuf;
- X#ifdef h_addr
- X def.h_addr_list = alist;
- X#endif
- X def.h_addr = (char *)&defaddr;
- X def.h_length = sizeof( struct in_addr );
- X def.h_addrtype = AF_INET;
- X def.h_aliases = 0;
- X hp = &def;
- X }
- X }
- X if (hp == NULL) {
- X fprintf(stderr, "%s: Unknown host.\n", machine);
- X return (-1);
- X }
- X
- X bzero((char *) &sin, sizeof(sin));
- X sin.sin_family = hp->h_addrtype;
- X sin.sin_port = sp->s_port;
- X#else EXCELAN
- X bzero((char *) &sin, sizeof(sin));
- X sin.sin_family = AF_INET;
- X sin.sin_port = htons(IPPORT_NNTP);
- X#endif EXCELAN
- X
- X /*
- X * The following is kinda gross. The name server under 4.3
- X * returns a list of addresses, each of which should be tried
- X * in turn if the previous one fails. However, 4.2 hostent
- X * structure doesn't have this list of addresses.
- X * Under 4.3, h_addr is a #define to h_addr_list[0].
- X * We use this to figure out whether to include the NS specific
- X * code...
- X */
- X
- X#ifdef h_addr
- X
- X /* get a socket and initiate connection -- use multiple addresses */
- X
- X for (cp = hp->h_addr_list; cp && *cp; cp++) {
- X s = socket(hp->h_addrtype, SOCK_STREAM, 0);
- X if (s < 0) {
- X perror("socket");
- X return (-1);
- X }
- X bcopy(*cp, (char *)&sin.sin_addr, hp->h_length);
- X
- X if (x < 0)
- X fprintf(stderr, "trying %s\n", inet_ntoa(sin.sin_addr));
- X x = connect(s, (struct sockaddr *)&sin, sizeof (sin));
- X if (x == 0)
- X break;
- X fprintf(stderr, "connection to %s: ", inet_ntoa(sin.sin_addr));
- X perror("");
- X (void) close(s);
- X }
- X if (x < 0) {
- X fprintf(stderr, "giving up...\n");
- X return (-1);
- X }
- X#else /* no name server */
- X#ifdef EXCELAN
- X if ((s = rresvport(SO_KEEPALIVE)) < 0)
- X {
- X /* Get the socket */
- X perror("socket");
- X return (-1);
- X }
- X /* set up addr for the connect */
- X sin.sin_addr.s_addr = rhost(machine);
- X if (sin.sin_addr.s_addr < 0){
- X fprintf(stderr, "%s: Unknown host.\n", machine);
- X return (-1);
- X }
- X /* And then connect */
- X
- X if (connect(s, &sin) < 0) {
- X perror("connect");
- X (void) close(s);
- X return (-1);
- X }
- X#else not EXCELAN
- X if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
- X perror("socket");
- X return (-1);
- X }
- X
- X /* And then connect */
- X
- X bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
- X if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
- X perror("connect");
- X (void) close(s);
- X return (-1);
- X }
- X
- X#endif not EXCELAN
- X#endif
- X
- X return (s);
- X}
- X
- X#ifdef DECNET
- X/*
- X * get_dnet_socket -- get us a socket connected to the news server.
- X *
- X * Parameters: "machine" is the machine the server is running on.
- X *
- X * Returns: Socket connected to the news server if
- X * all is ok, else -1 on error.
- X *
- X * Side effects: Connects to server.
- X *
- X * Errors: Printed via nerror.
- X */
- X
- Xget_dnet_socket(machine)
- Xchar *machine;
- X{
- X int s, area, node;
- X struct sockaddr_dn sdn;
- X struct nodeent *getnodebyname(), *np;
- X
- X bzero((char *) &sdn, sizeof(sdn));
- X
- X switch (s = sscanf( machine, "%d%*[.]%d", &area, &node )) {
- X case 1:
- X node = area;
- X area = 0;
- X case 2:
- X node += area*1024;
- X sdn.sdn_add.a_len = 2;
- X sdn.sdn_family = AF_DECnet;
- X sdn.sdn_add.a_addr[0] = node % 256;
- X sdn.sdn_add.a_addr[1] = node / 256;
- X break;
- X default:
- X if ((np = getnodebyname(machine)) == NULL) {
- X fprintf(stderr,
- X "%s: Unknown host.\n", machine);
- X return (-1);
- X } else {
- X bcopy(np->n_addr,
- X (char *) sdn.sdn_add.a_addr,
- X np->n_length);
- X sdn.sdn_add.a_len = np->n_length;
- X sdn.sdn_family = np->n_addrtype;
- X }
- X break;
- X }
- X sdn.sdn_objnum = 0;
- X sdn.sdn_flags = 0;
- X sdn.sdn_objnamel = strlen("NNTP");
- X bcopy("NNTP", &sdn.sdn_objname[0], sdn.sdn_objnamel);
- X
- X if ((s = socket(AF_DECnet, SOCK_STREAM, 0)) < 0) {
- X nerror("socket");
- X return (-1);
- X }
- X
- X /* And then connect */
- X
- X if (connect(s, (struct sockaddr *) &sdn, sizeof(sdn)) < 0) {
- X nerror("connect");
- X close(s);
- X return (-1);
- X }
- X
- X return (s);
- X}
- X#endif
- X
- X
- X
- X/*
- X * handle_server_response
- X *
- X * Print some informative messages based on the server's initial
- X * response code. This is here so inews, rn, etc. can share
- X * the code.
- X *
- X * Parameters: "response" is the response code which the
- X * server sent us, presumably from "server_init",
- X * above.
- X * "server" is the news server we got the
- X * response code from.
- X *
- X * Returns: -1 if the error is fatal (and we should exit).
- X * 0 otherwise.
- X *
- X * Side effects: None.
- X */
- X
- Xhandle_server_response(response, server)
- Xint response;
- Xchar *server;
- X{
- X switch (response) {
- X case OK_NOPOST: /* fall through */
- X printf(
- X "NOTE: This machine does not have permission to post articles.\n");
- X printf(
- X " Please don't waste your time trying.\n\n");
- X
- X case OK_CANPOST:
- X return (0);
- X break;
- X
- X case ERR_ACCESS:
- X printf(
- X "This machine does not have permission to use the %s news server.\n",
- X server);
- X return (-1);
- X break;
- X
- X default:
- X printf("Unexpected response code from %s news server: %d\n",
- X server, response);
- X return (-1);
- X break;
- X }
- X /*NOTREACHED*/
- X}
- X
- X
- X/*
- X * put_server -- send a line of text to the server, terminating it
- X * with CR and LF, as per ARPA standard.
- X *
- X * Parameters: "string" is the string to be sent to the
- X * server.
- X *
- X * Returns: Nothing.
- X *
- X * Side effects: Talks to the server.
- X *
- X * Note: This routine flushes the buffer each time
- X * it is called. For large transmissions
- X * (i.e., posting news) don't use it. Instead,
- X * do the fprintf's yourself, and then a final
- X * fflush.
- X */
- X
- Xvoid
- Xput_server(string)
- Xchar *string;
- X{
- X#ifdef DEBUG
- X fprintf(stderr, ">>> %s\n", string);
- X#endif
- X fprintf(ser_wr_fp, "%s\r\n", string);
- X (void) fflush(ser_wr_fp);
- X}
- X
- X
- X/*
- X * get_server -- get a line of text from the server. Strips
- X * CR's and LF's.
- X *
- X * Parameters: "string" has the buffer space for the
- X * line received.
- X * "size" is the size of the buffer.
- X *
- X * Returns: -1 on error, 0 otherwise.
- X *
- X * Side effects: Talks to server, changes contents of "string".
- X */
- X
- Xget_server(string, size)
- Xchar *string;
- Xint size;
- X{
- X register char *cp;
- X char *index();
- X
- X if (fgets(string, size, ser_rd_fp) == NULL)
- X return (-1);
- X
- X if ((cp = index(string, '\r')) != NULL)
- X *cp = '\0';
- X else if ((cp = index(string, '\n')) != NULL)
- X *cp = '\0';
- X#ifdef DEBUG
- X fprintf(stderr, "<<< %s\n", string);
- X#endif
- X
- X return (0);
- X}
- X
- X
- X/*
- X * close_server -- close the connection to the server, after sending
- X * the "quit" command.
- X *
- X * Parameters: None.
- X *
- X * Returns: Nothing.
- X *
- X * Side effects: Closes the connection with the server.
- X * You can't use "put_server" or "get_server"
- X * after this routine is called.
- X */
- X
- Xvoid
- Xclose_server()
- X{
- X char ser_line[256];
- X
- X if (ser_wr_fp == NULL || ser_rd_fp == NULL)
- X return;
- X
- X put_server("QUIT");
- X (void) get_server(ser_line, sizeof(ser_line));
- X
- X (void) fclose(ser_wr_fp);
- X (void) fclose(ser_rd_fp);
- X}
- X
- X#ifdef USG
- Xbzero(p, l)
- X register char *p;
- X register int l;
- X{
- X while (l-- > 0)
- X *p++ = 0;
- X}
- X#endif USG
- END_OF_FILE
- if test 11231 -ne `wc -c <'inews/clientlib.c'`; then
- echo shar: \"'inews/clientlib.c'\" unpacked with wrong size!
- fi
- # end of 'inews/clientlib.c'
- fi
- if test -f 'prefix.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'prefix.c'\"
- else
- echo shar: Extracting \"'prefix.c'\" \(3041 characters\)
- sed "s/^X//" >'prefix.c' <<'END_OF_FILE'
- X#include "config.h"
- X
- Ximport char *home_directory;
- Ximport char *news_directory;
- Ximport char *news_lib_directory;
- Ximport char *master_directory;
- Ximport char *help_directory;
- Ximport char *bin_directory;
- Ximport char *db_directory;
- Ximport char *db_data_directory;
- Ximport char *tmp_directory;
- Ximport char *log_file;
- X
- X#define SHELL_PREFIX 0x01
- X#define FULL_PREFIX 0x02
- X#define CONF_PREFIX 0x04
- X
- Xstatic make_nn_prefix(flag, f)
- Xint flag;
- XFILE *f;
- X{
- X char nl;
- X char buf[FILENAME], *p;
- X
- X nl = (flag & CONF_PREFIX) ? TAB : NL;
- X
- X if (flag & SHELL_PREFIX) {
- X#ifdef AVOID_SHELL_EXEC
- X fprintf(f, ":\n");
- X#else
- X fprintf(f, "#!/bin/sh\n");
- X#endif
- X fprintf(f, "\n# Generated by nn release %s at %s\n\n",
- X version_id, date_time((time_t)0));
- X }
- X fprintf(f, "VERSION=\"%s\"\n", version_id);
- X
- X#ifdef INEWS_PATH
- X strcpy(buf, INEWS_PATH);
- X fprintf(f, "INEWS=\"%s\"\n", buf);
- X if ((p = strrchr(buf, '/')) != NULL) *p = NUL;
- X fprintf(f, "INEWS_DIR=\"%s\"\n", buf);
- X#else
- X fprintf(f, "INEWS=\"%s/inews\"\n", news_lib_directory);
- X fprintf(f, "INEWS_DIR=\"%s\"\n", news_lib_directory);
- X#endif
- X
- X#ifndef OLD_AWK
- X#define OLD_AWK "awk"
- X#endif
- X fprintf(f, "AWK=\"%s\"\n", OLD_AWK);
- X
- X#ifdef NNTP
- X fprintf(f, "NNTP=true%c", nl);
- X fprintf(f, "ACTIVE=%s/ACTIVE\n", db_directory);
- X#ifndef CACHE_DIRECTORY
- X#define CACHE_DIRECTORY ""
- X#endif
- X fprintf(f, "NNTPCACHE=%s\n", CACHE_DIRECTORY);
- X#else
- X fprintf(f, "NNTP=false%c", nl);
- X fprintf(f, "ACTIVE=%s/active\n", news_lib_directory);
- X#endif
- X fprintf(f, "LOG=%s\n", log_file);
- X fprintf(f, "TMP=${TMPDIR-%s}\n", tmp_directory);
- X fprintf(f, "DB=%s\n", db_directory);
- X fprintf(f, "BIN=%s\n", bin_directory);
- X fprintf(f, "LIB=%s\n", lib_directory);
- X
- X if (flag & (FULL_PREFIX|CONF_PREFIX)) {
- X fprintf(f, "RECMAIL=\"%s\"\n", REC_MAIL);
- X fprintf(f, "SPOOL=%s\n", news_directory);
- X fprintf(f, "NLIB=%s\n", news_lib_directory);
- X fprintf(f, "MASTER=%s\n", master_directory);
- X fprintf(f, "HELP=%s\n", help_directory);
- X fprintf(f, "DBDATA=\"%s\"\n", db_data_directory ? db_data_directory : "");
- X fprintf(f, "OWNER=%s%c", OWNER, nl);
- X fprintf(f, "GROUP=%s\n", GROUP);
- X }
- X
- X if (FULL_PREFIX) {
- X fprintf(f, "UMAN_DIR=\"%s\"\n", USER_MAN_DIR);
- X fprintf(f, "UMAN_SECT=\"%s\"\n", USER_MAN_SECTION);
- X
- X fprintf(f, "SMAN_DIR=\"%s\"\n", SYS_MAN_DIR);
- X fprintf(f, "SMAN_SECT=\"%s\"\n", SYS_MAN_SECTION);
- X
- X fprintf(f, "DMAN_DIR=\"%s\"\n", DAEMON_MAN_DIR);
- X fprintf(f, "DMAN_SECT=\"%s\"\n", DAEMON_MAN_SECTION);
- X }
- X
- X if (flag & SHELL_PREFIX)
- X fprintf(f, "\n# ---- end of prefix\n\n");
- X}
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X if (argc != 2) exit(2);
- X
- X init_global(I_AM_MASTER);
- X
- X switch (argv[1][0]) {
- X case 'f':
- X make_nn_prefix(SHELL_PREFIX|FULL_PREFIX, stdout);
- X break;
- X case 'p':
- X make_nn_prefix(SHELL_PREFIX, stdout);
- X break;
- X case 'c':
- X make_nn_prefix(CONF_PREFIX, stdout);
- X break;
- X default:
- X exit(1);
- X }
- X exit(0);
- X}
- X
- Xnn_exit(n)
- X{
- X exit(n);
- X}
- X
- Xuser_error()
- X{
- X exit(8);
- X}
- X
- X#ifdef HAVE_JOBCONTROL
- Xsuspend_nn()
- X{}
- X#endif
- END_OF_FILE
- if test 3041 -ne `wc -c <'prefix.c'`; then
- echo shar: \"'prefix.c'\" unpacked with wrong size!
- fi
- # end of 'prefix.c'
- fi
- echo shar: End of archive 16 \(of 22\).
- cp /dev/null ark16isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 22 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
-